package com.dgut.app.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaUserService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dgut.app.service.UserService;
import com.dgut.common.config.WxAppConfig;
import com.dgut.common.dto.WxUserRegisterDTO;
import com.dgut.common.entity.UserBillTag;
import com.dgut.common.entity.WxUser;
import com.dgut.common.mapper.UserBillTagMapper;
import com.dgut.common.mapper.WxUserMapper;
import com.dgut.common.utils.ApiException;
import com.dgut.common.utils.ErrorEnum;
import com.dgut.common.utils.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.stereotype.Service;

/**
 * @author IT00ZYQ
 * @date 2021/4/5 12:32
 **/
@Service
@Slf4j
public class UserServiceImpl implements UserService {

    private final WxUserMapper userMapper;
    private final UserBillTagMapper tagMapper;

    public UserServiceImpl(WxUserMapper userMapper, UserBillTagMapper tagMapper) {
        this.userMapper = userMapper;
        this.tagMapper = tagMapper;
    }

    @Override
    public String register(WxUserRegisterDTO dto) {
        final WxMaUserService appService = WxAppConfig.wxMaService.getUserService();
        try {
            // 1.根据code获取sessionKey等信息
            WxMaJscode2SessionResult sessionInfo = appService.getSessionInfo(dto.getCode());
            // 2.判断用户是否已注册
            QueryWrapper<WxUser> wrapper = new QueryWrapper<>();
            wrapper.eq("openid", sessionInfo.getOpenid());
            if (userMapper.selectOne(wrapper) != null) {
                throw new ApiException(ErrorEnum.USER_REGISTERED);
            }

            // 3.用户信息校验
            if (!appService.checkUserInfo(sessionInfo.getSessionKey(), dto.getRawData(), dto.getSignature())) {
                throw new ApiException(ErrorEnum.CHECK_ERROR);
            }

            // 4.解密用户信息
            WxMaUserInfo userInfo = appService.getUserInfo(sessionInfo.getSessionKey(), dto.getEncryptedData(), dto.getIv());

            // 6.用户注册，写入数据库
            WxUser wxUser = WxUser.builder()
                    .nickName(userInfo.getNickName())
                    .avatarUrl(userInfo.getAvatarUrl())
                    .gender(Integer.valueOf(userInfo.getGender()))
                    .openid(sessionInfo.getOpenid())
                    .build();
            userMapper.insert(wxUser);

            // 用户绑定默认账单标签
            bindBillTag(wxUser.getId());

            // 7.返回token
            return JwtUtil.getToken(wxUser.getOpenid());
        } catch (WxErrorException e) {
            log.error("【微信用户注册失败】:{}", e.getMessage());
            throw new ApiException(ErrorEnum.WX_USER_REGISTER_FAIL);
        }
    }

    @Override
    public String login(String code) {
        try {
            WxMaJscode2SessionResult sessionInfo = WxAppConfig.wxMaService.getUserService().getSessionInfo(code);
            // 查询用户
            QueryWrapper<WxUser> wrapper = new QueryWrapper<>();
            wrapper.eq("openid", sessionInfo.getOpenid());
            WxUser user = userMapper.selectOne(wrapper);
            if (user == null) {
                throw new ApiException(ErrorEnum.USER_NO_EXIST);
            }
            // 生成token并返回
            return JwtUtil.getToken(user.getOpenid());
        } catch (WxErrorException e) {
            log.error("【微信用户登录失败】:{}", e.getMessage());
            throw new ApiException(ErrorEnum.WX_USER_LOGIN_FAIL);
        }
    }

    @Override
    public WxUser userInfo(String token) {
        log.info(token);
        return JwtUtil.getUser(token);
    }

    /**
     * 用户绑定默认的账单标签
     * @param userId
     */
    private void bindBillTag(Integer userId){
        int[] tags = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
        for (int tag : tags) {
            tagMapper.insert(UserBillTag.builder()
                    .tagId(tag)
                    .userId(userId)
                    .build());
        }
    }



}
